home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tiff / tools / fax2tiff.c < prev    next >
C/C++ Source or Header  |  1992-02-10  |  9KB  |  284 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/fax2tiff.c,v 1.15 92/02/10 19:04:17 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /* 
  30.  * Convert a CCITT Group 3 FAX file to TIFF Group 3 format.
  31.  */
  32. #include <stdio.h>
  33. #include <math.h>        /* for atof declaration */
  34. #include "tiffioP.h"
  35.  
  36. TIFF    faxTIFF;
  37. #define XSIZE        1728
  38. u_char    rowbuf[howmany(XSIZE,8)];
  39. u_char    refbuf[howmany(XSIZE,8)];
  40.  
  41. int    verbose;
  42. int    stretch;
  43. u_short    badfaxrun;
  44. u_long    badfaxlines;
  45.  
  46. usage()
  47. {
  48.     fprintf(stderr, "usage: fax2tiff [-2BLMW] [-R inres] [-14cfmpsv] [-o out.tif] faxfile ...\n");
  49.     exit(-1);
  50. }
  51.  
  52. main(argc, argv)
  53.     int argc;
  54.     char *argv[];
  55. {
  56.     FILE *in;
  57.     TIFF *out = NULL;
  58.     int compression = COMPRESSION_CCITTFAX3;
  59.     int fillorder = FILLORDER_LSB2MSB;
  60.     long group3options = GROUP3OPT_FILLBITS;
  61.     int photometric = PHOTOMETRIC_MINISWHITE;
  62.     int isClassF = 1;
  63.     int rows;
  64.     int c;
  65.     int pn, npages;
  66.     extern int optind;
  67.     extern char *optarg;
  68.  
  69.     bzero(&faxTIFF, sizeof (faxTIFF));
  70.     TIFFSetField(&faxTIFF, TIFFTAG_IMAGEWIDTH,    XSIZE);
  71.     TIFFSetField(&faxTIFF, TIFFTAG_SAMPLESPERPIXEL,    1);
  72.     TIFFSetField(&faxTIFF, TIFFTAG_BITSPERSAMPLE,    1);
  73.     TIFFSetField(&faxTIFF, TIFFTAG_FILLORDER,    FILLORDER_LSB2MSB);
  74.     TIFFSetField(&faxTIFF, TIFFTAG_PLANARCONFIG,    PLANARCONFIG_CONTIG);
  75.     TIFFSetField(&faxTIFF, TIFFTAG_PHOTOMETRIC,    PHOTOMETRIC_MINISWHITE);
  76.     TIFFSetField(&faxTIFF, TIFFTAG_YRESOLUTION,    196.);
  77.     TIFFSetField(&faxTIFF, TIFFTAG_RESOLUTIONUNIT,    RESUNIT_INCH);
  78.     /* NB: this is normally setup when a directory is read */
  79.     faxTIFF.tif_scanlinesize = TIFFScanlineSize(&faxTIFF);
  80.  
  81.     while ((c = getopt(argc, argv, "R:o:2BLMW14cflmpsvwz")) != -1)
  82.         switch (c) {
  83.             /* input-related options */
  84.         case '2':        /* input is 2d-encoded */
  85.             TIFFSetField(&faxTIFF,
  86.                 TIFFTAG_GROUP3OPTIONS, GROUP3OPT_2DENCODING);
  87.             break;
  88.         case 'B':        /* input has 0 mean black */
  89.             TIFFSetField(&faxTIFF,
  90.                 TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  91.             break;
  92.         case 'L':        /* input has lsb-to-msb fillorder */
  93.             TIFFSetField(&faxTIFF,
  94.                 TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
  95.             break;
  96.         case 'M':        /* input has msb-to-lsb fillorder */
  97.             TIFFSetField(&faxTIFF,
  98.                 TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
  99.             break;
  100.         case 'R':        /* input resolution */
  101.             TIFFSetField(&faxTIFF,
  102.                 TIFFTAG_YRESOLUTION, atof(optarg));
  103.             break;
  104.         case 'W':        /* input has 0 mean white */
  105.             TIFFSetField(&faxTIFF,
  106.                 TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
  107.             break;
  108.  
  109.             /* output-related options */
  110.         case '1':        /* generate 1d-encoded output */
  111.             group3options &= ~GROUP3OPT_2DENCODING;
  112.             break;
  113.         case '4':        /* generate g4-encoded output */
  114.             compression = COMPRESSION_CCITTFAX4;
  115.             break;
  116.         case 'c':        /* generate "classic" g3 format */
  117.             isClassF = 0;
  118.             break;
  119.         case 'f':        /* generate Class F format */
  120.             isClassF = 1;
  121.             break;
  122.         case 'm':        /* output's fillorder is msb-to-lsb */
  123.             fillorder = FILLORDER_MSB2LSB;
  124.             break;
  125.         case 'o':
  126.             out = TIFFOpen(optarg, "w");
  127.             if (out == NULL)
  128.                 exit(-2);
  129.             break;
  130.         case 'p':        /* zero pad output scanline EOLs */
  131.             group3options &= ~GROUP3OPT_FILLBITS;
  132.             break;
  133.         case 's':        /* stretch image by dup'ng scanlines */
  134.             stretch = 1;
  135.             break;
  136.         case 'w':        /* undocumented -- for testing */
  137.             photometric = PHOTOMETRIC_MINISBLACK;
  138.             break;
  139.  
  140.         case 'z':        /* undocumented -- for testing */
  141.             compression = COMPRESSION_LZW;
  142.             break;
  143.  
  144.         case 'v':        /* -v for info */
  145.             verbose++;
  146.             break;
  147.         case '?':
  148.             usage();
  149.             /*NOTREACHED*/
  150.         }
  151.     if (out == NULL) {
  152.         out = TIFFOpen("fax.tif", "w");
  153.         if (out == NULL)
  154.             exit(-2);
  155.     }
  156.     faxTIFF.tif_fillorder = out->tif_fillorder;    /* XXX */
  157.  
  158.     npages = argc - optind;
  159.     if (npages < 1)
  160.         usage();
  161.  
  162.     /* NB: this must be done after directory info is setup */
  163.     TIFFSetField(&faxTIFF, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
  164.     for (pn = 0; optind < argc; pn++, optind++) {
  165.         in = fopen(argv[optind], "r");
  166.         if (in == NULL) {
  167.             fprintf(stderr,
  168.                 "%s: %s: Can not open\n", argv[0], argv[optind]);
  169.             continue;
  170.         }
  171.         faxTIFF.tif_fd = fileno(in);
  172.         faxTIFF.tif_name = argv[optind];
  173.         TIFFSetField(out, TIFFTAG_IMAGEWIDTH, XSIZE);
  174.         TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
  175.         TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  176.         TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
  177.         TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  178.         TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
  179.         if (compression == COMPRESSION_CCITTFAX3) {
  180.             TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
  181.             TIFFModeCCITTFax3(out, isClassF);
  182.         }
  183.         if (compression == COMPRESSION_CCITTFAX3 ||
  184.             compression == COMPRESSION_CCITTFAX4)
  185.             TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, -1L);
  186.         else
  187.             TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  188.                 (u_long) (8*1024)/TIFFScanlineSize(out));
  189.         TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  190.         TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  191.         TIFFSetField(out, TIFFTAG_SOFTWARE, "fax2tiff");
  192.         TIFFSetField(out, TIFFTAG_XRESOLUTION, 204.0);
  193.         if (!stretch) {
  194.             float yres;
  195.             TIFFGetField(&faxTIFF, TIFFTAG_YRESOLUTION, &yres);
  196.             TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
  197.         } else
  198.             TIFFSetField(out, TIFFTAG_YRESOLUTION, 196.);
  199.         TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  200.         TIFFSetField(out, TIFFTAG_PAGENUMBER, pn+1, npages);
  201.  
  202.         rows = copyFaxFile(&faxTIFF, out);
  203.         fclose(in);
  204.  
  205.         TIFFSetField(out, TIFFTAG_IMAGELENGTH, rows);
  206.  
  207.         if (verbose) {
  208.             fprintf(stderr, "%s:\n", argv[optind]);
  209.             fprintf(stderr, "%d rows in input\n", rows);
  210.             fprintf(stderr, "%d total bad rows\n", badfaxlines);
  211.             fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
  212.         }
  213.         if (compression == COMPRESSION_CCITTFAX3 && isClassF) {
  214.             TIFFSetField(out, TIFFTAG_BADFAXLINES, badfaxlines);
  215.             TIFFSetField(out, TIFFTAG_CLEANFAXDATA, badfaxlines ?
  216.                 CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
  217.             TIFFSetField(out, TIFFTAG_CONSECUTIVEBADFAXLINES, badfaxrun);
  218.         }
  219.         TIFFWriteDirectory(out);
  220.     }
  221.     TIFFClose(out);
  222.     exit(0);
  223. }
  224.  
  225. copyFaxFile(tifin, tifout)
  226.     TIFF *tifin, *tifout;
  227. {
  228.     long row;
  229.     u_short badrun;
  230.     int ok;
  231.  
  232.     tifin->tif_rawdatasize = TIFFGetFileSize(tifin->tif_fd);
  233.     tifin->tif_rawdata = malloc(tifin->tif_rawdatasize);
  234.     if (!ReadOK(tifin->tif_fd, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
  235.         TIFFError(tifin->tif_name, "%s: Read error at scanline 0");
  236.         return (0);
  237.     }
  238.     tifin->tif_rawcp = tifin->tif_rawdata;
  239.     tifin->tif_rawcc = tifin->tif_rawdatasize;
  240.  
  241.     (*tifin->tif_predecode)(tifin);
  242.     tifin->tif_row = 0;
  243.     badfaxlines = 0;
  244.     badfaxrun = 0;
  245.  
  246.     bzero(refbuf, sizeof (refbuf));
  247.     row = 0;
  248.     badrun = 0;        /* current run of bad lines */
  249.     while (tifin->tif_rawcc > 0) {
  250.         ok = (*tifin->tif_decoderow)(tifin, rowbuf, sizeof (rowbuf), 0);
  251.         if (!ok) {
  252.             badfaxlines++;
  253.             badrun++;
  254.             /* regenerate line from previous good line */
  255.             bcopy(refbuf, rowbuf, sizeof (rowbuf));
  256.         } else {
  257.             if (badrun > badfaxrun)
  258.                 badfaxrun = badrun;
  259.             badrun = 0;
  260.             bcopy(rowbuf, refbuf, sizeof (rowbuf));
  261.         }
  262.         tifin->tif_row++;
  263.  
  264.         if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
  265.             fprintf(stderr, "%s: Write error at row %ld.\n",
  266.                 tifout->tif_name, row);
  267.             break;
  268.         }
  269.         row++;
  270.         if (stretch) {
  271.             if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
  272.                 fprintf(stderr, "%s: Write error at row %ld.\n",
  273.                     tifout->tif_name, row);
  274.                 break;
  275.             }
  276.             row++;
  277.         }
  278.     }
  279.     if (badrun > badfaxrun)
  280.         badfaxrun = badrun;
  281.     free(tifin->tif_rawdata);
  282.     return (row);
  283. }
  284.